package models

import (
	"encoding/json"
	"github.com/ahmetb/go-linq/v3"
	"github.com/beego/beego/v2/client/orm"
	"time"
)

type Log struct {
	BModel
	ReqUrl    string `orm:"column(req_url)" json:"req_url"`
	ReqMethod string `orm:"column(req_method)" json:"req_method"`
	ReqBody   string `orm:"column(req_body)" json:"req_body"`
	ReqIp     string `orm:"column(req_ip)" json:"req_ip"`
	Result    string `orm:"column(result)" json:"result"`
}
type LogInfoDTO struct {
	Log
	RealName string `json:"real_name" orm:"column(real_name)"`
	UserName string `json:"user_name" orm:"column(user_name)"`
}

//MarshalJSON 格式化时间
func (tb LogInfoDTO) MarshalJSON() ([]byte, error) {

	type Alias LogInfoDTO

	return json.Marshal(struct {
		Alias
		CreatedAt string `json:"created_at"`
		UpdatedAt string `json:"updated_at"`
	}{
		Alias:     (Alias)(tb),
		CreatedAt: tb.CreatedAt.Format("2006-01-02 15:04:05"),
		UpdatedAt: tb.UpdatedAt.Format("2006-01-02 15:04:05"),
	})
}

func NewLog() *Log {
	return &Log{}
}

func (tb *Log) TableName() string {
	return LogTable
}

type LoggerReq struct {
	ReqUrl    string `orm:"column(req_url)" json:"req_url"`
	ReqMethod string `orm:"column(req_method)" json:"req_method"`
	ReqBody   string `orm:"column(req_body)" json:"req_body"`
	ReqIp     string `orm:"column(req_ip)" json:"req_ip"`
	Result    string `orm:"column(result)" json:"result"`
}

func (tb *Log) Logger(uid uint64, req LoggerReq) (err error) {
	db := orm.NewOrm()

	now := time.Now()

	tb.ReqUrl = req.ReqUrl
	tb.ReqMethod = req.ReqMethod
	tb.UpdatedAt = now
	tb.CreatedAt = now
	tb.CreatedBy = uid
	tb.UpdatedBy = uid
	tb.ReqBody = req.ReqBody
	tb.ReqIp = req.ReqIp
	tb.Result = req.Result
	_, err = db.Insert(tb)
	return
}

func (tb *Log) GetByPage(pageSize, pageIndex uint64, startTime, endTime string) (lst []LogInfoDTO, count uint64, err error) {

	offset := (pageIndex - 1) * pageSize
	var ls []Log
	db := orm.NewOrm()
	q := db.QueryTable(tb).OrderBy("-created_at")
	if len(startTime) > 0 {
		q = q.Filter("created_at__gte", startTime)
	}
	if len(endTime) > 0 {

		et, _ := time.ParseInLocation("2006-01-02", endTime, time.Local)
		endTime = et.AddDate(0, 0, 1).Format("2006-01-02")
		q = q.Filter("created_at__lt", endTime)

	}
	c, e := q.Count()
	count = uint64(c)
	err = e
	if count <= 0 {

		return
	}
	_, err = q.Offset(offset).Limit(pageSize).All(&ls)

	var (
		us   []User
		uids []uint64
	)

	linq.From(ls).SelectT(func(s Log) uint64 { return s.CreatedBy }).ToSlice(&uids)
	_, err = db.QueryTable(NewUser()).Filter("id__in", uids).All(&us)

	for _, v := range ls {
		rName := ""
		uName := ""
		if u, ok := linq.From(us).FirstWithT(func(f User) bool { return f.ID == v.CreatedBy }).(User); ok {
			uName = u.UserName
			rName = u.RealName
		}
		lst = append(lst, LogInfoDTO{
			Log:      v,
			RealName: rName,
			UserName: uName,
		})
	}
	return

}

func (tb *Log) Find(id uint64) (m *LogInfoDTO, err error) {

	m = &LogInfoDTO{}

	db := orm.NewOrm()
	q := db.QueryTable(tb).Filter("id", id)
	err = q.One(&m.Log)
	if m.ID <= 0 {
		m = nil
	}

	var u User
	db.QueryTable(NewUser()).Filter("id", m.CreatedBy).One(&u)
	m.RealName = u.RealName
	m.UserName = u.UserName
	return

}
